######################################################################
# skypeapi-twisted-test-osx.py
#
# This file is part of the pyskype project, please see also
# http://code.google.com/p/pyskype/
#
# This is a proof of concept that wrapping the Skype API using
# Python on Mac OS X using PyObjC does work.
#
# The application does basically:
#
# - load the Skype Framework and construct proxy objects for it
# - defines the informal protocol needed for the delegate which
#   gets the notifications from skype
# - creates a delegate object
# - creates a main loop
# - sets the delegate
# - connects to skype
# - waits
# - sends a "PROTOCOL 1" Command
#
# After we're connected, the Skype API calls our delegate objects
# "skypeAttachResponse_" method, and then we get notifications from the
# API through "skypeNotificationReceived_".
#
# This code assumes a few things:
#
# - pyobjc is installed and working
# - the Skype API is installed in the current user's library
#   directory
#
# (C) 2006 Stefan Eletzhofer <stefan.eletzhofer@googlemail.com>
#
# This code is licensed under the GNU GPL 2.0
#
#
# $Id: skypeapi-twisted-test-osx.py 2 2006-10-24 22:55:59Z stefan.eletzhofer $


import skypeapi

from twisted.application import internet, service
from twisted.internet import defer, protocol
from twisted.protocols import basic
from twisted.python import log

class SkypeShellProtocol(basic.LineReceiver):
    def connectionMade(self):
        log.msg("connect", self.transport )
        d = self.skype_connect()
        d.addCallback( lambda x: self.transport.write( "Connection made.\n" ) )
        d.addErrback( lambda x: self.transport.write( "Connection failed.\n" ) )

    def lineReceived(self, line ):
        d = self.skype_command( line )
        d.addBoth( lambda msg: self.transport.write( "%s\n" % msg ) )

    def connectionLost(self, reason):
        pass

class SkypeService(service.Service):
    def __init__(self ):
        self.appname = "SkypeService"
        self.delegate = skypeapi.Delegate.alloc().init( self.appname ).retain()
        skypeapi.SkypeAPI.setSkypeDelegate_(self.delegate)
        self.delegate.skype_attach_response = self.skype_attach_response
        self.delegate.skype_notification = self.skype_notification
        self.deferred_connect = None
        self.deferred_command = None

    def getSkypeShellFactory(self):
        log.msg( "getSkypeShellFactory" )
        factory = protocol.ServerFactory()
        factory.protocol = SkypeShellProtocol
        factory.protocol.skype_connect = self.skype_connect
        factory.protocol.skype_command = self.skype_command
        return factory

    def skype_attach_response(self, code ):
        log.msg( "ATTACH RESPONSE: %d" % code )
        if int(code) == 1:
            self.deferred_connect.callback( code )
        else:
            self.deferred_connect.errback( code )

    def skype_notification( self, message ):
        log.msg( "NOTIFICATION: %s" % message )
        if self.deferred_command:
            self.deferred_command.callback( message )
            self.deferred_command = None

    def skype_connect(self):
        log.msg( "CONNECT" )
        self.deferred_connect = defer.Deferred()
        skypeapi.SkypeAPI.connect()
        return self.deferred_connect

    def skype_command(self, message ):
        log.msg( "=> %s" % message )
        if self.deferred_command:
            log.msg( "skype_command BUSY" )
            return defer.succeed( "BUSY" )

        self.deferred_command = defer.Deferred()
        skypeapi.SkypeAPI.sendSkypeCommand_( u"%s" % message )
        return self.deferred_command

application = service.Application( "SkypeShell" )

s = SkypeService()

skypeshell = internet.TCPServer( 6666, s.getSkypeShellFactory() )
skypeshell.setServiceParent( service.IServiceCollection(application) )

# vim: set ts=4 sw=4 expandtab:
